home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Peter's Final Project / jpeg-5b / wrtarga.c < prev   
Text File  |  1994-07-28  |  8KB  |  254 lines

  1. /*
  2.  * wrtarga.c
  3.  *
  4.  * Copyright (C) 1991-1994, Thomas G. Lane.
  5.  * This file is part of the Independent JPEG Group's software.
  6.  * For conditions of distribution and use, see the accompanying README file.
  7.  *
  8.  * This file contains routines to write output images in Targa format.
  9.  *
  10.  * These routines may need modification for non-Unix environments or
  11.  * specialized applications.  As they stand, they assume output to
  12.  * an ordinary stdio stream.
  13.  *
  14.  * Based on code contributed by Lee Daniel Crocker.
  15.  */
  16.  
  17. #include "cdjpeg.h"        /* Common decls for cjpeg/djpeg applications */
  18.  
  19. #ifdef TARGA_SUPPORTED
  20.  
  21.  
  22. /*
  23.  * To support 12-bit JPEG data, we'd have to scale output down to 8 bits.
  24.  * This is not yet implemented.
  25.  */
  26.  
  27. #if BITS_IN_JSAMPLE != 8
  28.   Sorry, this code only copes with 8-bit JSAMPLEs. /* deliberate syntax err */
  29. #endif
  30.  
  31. /*
  32.  * The output buffer needs to be writable by fwrite().  On PCs, we must
  33.  * allocate the buffer in near data space, because we are assuming small-data
  34.  * memory model, wherein fwrite() can't reach far memory.  If you need to
  35.  * process very wide images on a PC, you might have to compile in large-memory
  36.  * model, or else replace fwrite() with a putc() loop --- which will be much
  37.  * slower.
  38.  */
  39.  
  40.  
  41. /* Private version of data destination object */
  42.  
  43. typedef struct {
  44.   struct djpeg_dest_struct pub;    /* public fields */
  45.  
  46.   char *iobuffer;        /* physical I/O buffer */
  47.   JDIMENSION buffer_width;    /* width of one row */
  48. } tga_dest_struct;
  49.  
  50. typedef tga_dest_struct * tga_dest_ptr;
  51.  
  52.  
  53. LOCAL void
  54. write_header (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo, int num_colors)
  55. /* Create and write a Targa header */
  56. {
  57.   char targaheader[18];
  58.  
  59.   /* Set unused fields of header to 0 */
  60.   MEMZERO(targaheader, SIZEOF(targaheader));
  61.  
  62.   if (num_colors > 0) {
  63.     targaheader[1] = 1;        /* color map type 1 */
  64.     targaheader[5] = (char) (num_colors & 0xFF);
  65.     targaheader[6] = (char) (num_colors >> 8);
  66.     targaheader[7] = 24;    /* 24 bits per cmap entry */
  67.   }
  68.  
  69.   targaheader[12] = (char) (cinfo->output_width & 0xFF);
  70.   targaheader[13] = (char) (cinfo->output_width >> 8);
  71.   targaheader[14] = (char) (cinfo->output_height & 0xFF);
  72.   targaheader[15] = (char) (cinfo->output_height >> 8);
  73.   targaheader[17] = 0x20;    /* Top-down, non-interlaced */
  74.  
  75.   if (cinfo->out_color_space == JCS_GRAYSCALE) {
  76.     targaheader[2] = 3;        /* image type = uncompressed gray-scale */
  77.     targaheader[16] = 8;    /* bits per pixel */
  78.   } else {            /* must be RGB */
  79.     if (num_colors > 0) {
  80.       targaheader[2] = 1;    /* image type = colormapped RGB */
  81.       targaheader[16] = 8;
  82.     } else {
  83.       targaheader[2] = 2;    /* image type = uncompressed RGB */
  84.       targaheader[16] = 24;
  85.     }
  86.   }
  87.  
  88.   if (JFWRITE(dinfo->output_file, targaheader, 18) != (size_t) 18)
  89.     ERREXIT(cinfo, JERR_FILE_WRITE);
  90. }
  91.  
  92.  
  93. /*
  94.  * Write some pixel data.
  95.  * In this module rows_supplied will always be 1.
  96.  */
  97.  
  98. METHODDEF void
  99. put_pixel_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  100.         JDIMENSION rows_supplied)
  101. /* used for unquantized full-color output */
  102. {
  103.   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  104.   register JSAMPROW inptr;
  105.   register char * outptr;
  106.   register JDIMENSION col;
  107.  
  108.   inptr = dest->pub.buffer[0];
  109.   outptr = dest->iobuffer;
  110.   for (col = cinfo->output_width; col > 0; col--) {
  111.     outptr[0] = (char) GETJSAMPLE(inptr[2]); /* RGB to BGR order */
  112.     outptr[1] = (char) GETJSAMPLE(inptr[1]);
  113.     outptr[2] = (char) GETJSAMPLE(inptr[0]);
  114.     inptr += 3, outptr += 3;
  115.   }
  116.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  117. }
  118.  
  119. METHODDEF void
  120. put_gray_rows (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  121.            JDIMENSION rows_supplied)
  122. /* used for grayscale OR quantized color output */
  123. {
  124.   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  125.   register JSAMPROW inptr;
  126.   register char * outptr;
  127.   register JDIMENSION col;
  128.  
  129.   inptr = dest->pub.buffer[0];
  130.   outptr = dest->iobuffer;
  131.   for (col = cinfo->output_width; col > 0; col--) {
  132.     *outptr++ = (char) GETJSAMPLE(*inptr++);
  133.   }
  134.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  135. }
  136.  
  137.  
  138. /*
  139.  * Write some demapped pixel data when color quantization is in effect.
  140.  * For Targa, this is only applied to grayscale data.
  141.  */
  142.  
  143. METHODDEF void
  144. put_demapped_gray (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo,
  145.            JDIMENSION rows_supplied)
  146. {
  147.   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  148.   register JSAMPROW inptr;
  149.   register char * outptr;
  150.   register JSAMPROW color_map0 = cinfo->colormap[0];
  151.   register JDIMENSION col;
  152.  
  153.   inptr = dest->pub.buffer[0];
  154.   outptr = dest->iobuffer;
  155.   for (col = cinfo->output_width; col > 0; col--) {
  156.     *outptr++ = (char) GETJSAMPLE(color_map0[GETJSAMPLE(*inptr++)]);
  157.   }
  158.   (void) JFWRITE(dest->pub.output_file, dest->iobuffer, dest->buffer_width);
  159. }
  160.  
  161.  
  162. /*
  163.  * Startup: write the file header.
  164.  */
  165.  
  166. METHODDEF void
  167. start_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  168. {
  169.   tga_dest_ptr dest = (tga_dest_ptr) dinfo;
  170.   int num_colors, i;
  171.   FILE *outfile;
  172.  
  173.   if (cinfo->out_color_space == JCS_GRAYSCALE) {
  174.     /* Targa doesn't have a mapped grayscale format, so we will */
  175.     /* demap quantized gray output.  Never emit a colormap. */
  176.     write_header(cinfo, dinfo, 0);
  177.     if (cinfo->quantize_colors)
  178.       dest->pub.put_pixel_rows = put_demapped_gray;
  179.     else
  180.       dest->pub.put_pixel_rows = put_gray_rows;
  181.   } else if (cinfo->out_color_space == JCS_RGB) {
  182.     if (cinfo->quantize_colors) {
  183.       /* We only support 8-bit colormap indexes, so only 256 colors */
  184.       num_colors = cinfo->actual_number_of_colors;
  185.       if (num_colors > 256)
  186.     ERREXIT1(cinfo, JERR_TOO_MANY_COLORS, num_colors);
  187.       write_header(cinfo, dinfo, num_colors);
  188.       /* Write the colormap.  Note Targa uses BGR byte order */
  189.       outfile = dest->pub.output_file;
  190.       for (i = 0; i < num_colors; i++) {
  191.     putc(GETJSAMPLE(cinfo->colormap[2][i]), outfile);
  192.     putc(GETJSAMPLE(cinfo->colormap[1][i]), outfile);
  193.     putc(GETJSAMPLE(cinfo->colormap[0][i]), outfile);
  194.       }
  195.       dest->pub.put_pixel_rows = put_gray_rows;
  196.     } else {
  197.       write_header(cinfo, dinfo, 0);
  198.       dest->pub.put_pixel_rows = put_pixel_rows;
  199.     }
  200.   } else {
  201.     ERREXIT(cinfo, JERR_TGA_COLORSPACE);
  202.   }
  203. }
  204.  
  205.  
  206. /*
  207.  * Finish up at the end of the file.
  208.  */
  209.  
  210. METHODDEF void
  211. finish_output_tga (j_decompress_ptr cinfo, djpeg_dest_ptr dinfo)
  212. {
  213.   /* Make sure we wrote the output file OK */
  214.   fflush(dinfo->output_file);
  215.   if (ferror(dinfo->output_file))
  216.     ERREXIT(cinfo, JERR_FILE_WRITE);
  217. }
  218.  
  219.  
  220. /*
  221.  * The module selection routine for Targa format output.
  222.  */
  223.  
  224. GLOBAL djpeg_dest_ptr
  225. jinit_write_targa (j_decompress_ptr cinfo)
  226. {
  227.   tga_dest_ptr dest;
  228.  
  229.   /* Create module interface object, fill in method pointers */
  230.   dest = (tga_dest_ptr)
  231.       (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  232.                   SIZEOF(tga_dest_struct));
  233.   dest->pub.start_output = start_output_tga;
  234.   dest->pub.finish_output = finish_output_tga;
  235.  
  236.   /* Calculate output image dimensions so we can allocate space */
  237.   jpeg_calc_output_dimensions(cinfo);
  238.  
  239.   /* Create I/O buffer.  Note we make this near on a PC. */
  240.   dest->buffer_width = cinfo->output_width * cinfo->output_components;
  241.   dest->iobuffer = (char *)
  242.     (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo, JPOOL_IMAGE,
  243.                 (size_t) (dest->buffer_width * SIZEOF(char)));
  244.  
  245.   /* Create decompressor output buffer. */
  246.   dest->pub.buffer = (*cinfo->mem->alloc_sarray)
  247.     ((j_common_ptr) cinfo, JPOOL_IMAGE, dest->buffer_width, (JDIMENSION) 1);
  248.   dest->pub.buffer_height = 1;
  249.  
  250.   return (djpeg_dest_ptr) dest;
  251. }
  252.  
  253. #endif /* TARGA_SUPPORTED */
  254.